package cn.miju.ser.unionpay.service;

import cn.miju.database.constant.DbConstant;
import cn.miju.database.entity.Merchant;
import cn.miju.database.entity.PayOrder;
import cn.miju.database.entity.RefundOrder;
import cn.miju.database.service.MerchantDataService;
import cn.miju.database.service.PayOrderDataService;
import cn.miju.database.service.RefundOrderDataService;
import cn.miju.ser.common.rocketmq.Topic;
import cn.miju.unionpay.model.PayResultNotifyRequest;
import cn.miju.unionpay.model.RefundResultNotifyRequest;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Objects;

/**
 * <pre>
 * 银联云闪付回调接口实现
 * </pre>
 *
 * @author zhuming
 * @version 1.0.0
 * @since 2023-03-16 15:29
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UnionPayCallbackServiceImpl implements UnionPayCallbackService {

    private final PayOrderDataService payOrderDataService;
    private final RefundOrderDataService refundOrderDataService;
    private final MerchantDataService merchantDataService;
    private final RocketMQTemplate rocketMQTemplate;

    /**
     * 支付结果通知
     *
     * @param request 入参
     */
    @Async
    @Override
    public void payCallbackNotify(PayResultNotifyRequest request) {
        PayOrder payOrder = payOrderDataService.getOne(new LambdaQueryWrapper<PayOrder>().
                eq(PayOrder::getPlatTradeNo, request.getOrderId()).
                in(PayOrder::getStatus, DbConstant.PayOrderStatus.WAITING, DbConstant.PayOrderStatus.TIMEOUT));
        if (Objects.isNull(payOrder)) {
            log.error("回调通知订单{}不存在!", request.getOrderId());
            return;
        }
        String tradeStatus;
        switch (request.getRespCode()) {
            case "00":
                tradeStatus = DbConstant.PayOrderStatus.SUCCESS;
                break;
            case "45":
                tradeStatus = DbConstant.PayOrderStatus.ALL_REFUND;
                break;
            case "46":
                tradeStatus = DbConstant.PayOrderStatus.CANCEL;
                break;
            default:
                tradeStatus = DbConstant.PayOrderStatus.FAIL;
                break;
        }
        payOrder.setStatus(tradeStatus);
        payOrder.setTradeNo(request.getQueryId());
        payOrder.setPayOrderTime(StringUtils.isBlank(request.getTxnTime()) ? LocalDateTime.now() : LocalDateTime.parse(request.getTxnTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
        payOrder.setUpdatedTime(LocalDateTime.now());
        payOrderDataService.updateById(payOrder);
        // 通知接入方
        Merchant merchant = merchantDataService.getById(payOrder.getMerchantId());
        if (StringUtils.isNotBlank(merchant.getPayNotifyUrl())) {
            rocketMQTemplate.syncSend(Topic.PAY_RESULT_NOTIFY_TOPIC, MessageBuilder.withPayload(payOrder.getId()).build(), 3000);
        }
    }

    /**
     * 退款结果通知
     *
     * @param request 入参
     */
    @Override
    public void refundResultNotify(RefundResultNotifyRequest request) {
        RefundOrder refundOrder = refundOrderDataService.getOne(new LambdaQueryWrapper<RefundOrder>().
                eq(RefundOrder::getPlatRefundNo, request.getOrderId()).
                eq(RefundOrder::getStatus, DbConstant.RefundOrderStatus.PROCESSING));
        if (Objects.isNull(refundOrder)) {
            log.error("回调通知退单{}不存在!", request.getOrderId());
            return;
        }
        refundOrder.setStatus(Objects.equals(request.getRespCode(), "00") ? DbConstant.RefundOrderStatus.SUCCESS : DbConstant.PayOrderStatus.FAIL);
        refundOrder.setTradeNo(request.getQueryId());
        refundOrder.setRefundResult(Objects.equals(request.getRespCode(), "00") ? "成功" : "失败");
        refundOrder.setRefundTime(StringUtils.isBlank(request.getTxnTime()) ? LocalDateTime.now() : LocalDateTime.parse(request.getTxnTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
        refundOrder.setUpdatedTime(LocalDateTime.now());
        refundOrderDataService.updateById(refundOrder);
        // 通知接入方
        Merchant merchant = merchantDataService.getById(refundOrder.getMerchantId());
        if (StringUtils.isNotBlank(merchant.getRefundNotifyUrl())) {
            rocketMQTemplate.syncSend(Topic.REFUND_RESULT_NOTIFY_TOPIC, MessageBuilder.withPayload(refundOrder.getId()).build(), 3000);
        }
    }
}
